package com.example.activiti.controller;

import com.example.activiti.dto.HistoryTaskDto;
import com.example.activiti.dto.TaskDto;
import com.example.activiti.entity.User;
import com.example.activiti.mapper.UserMapper;
import com.example.common.ResultDto;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api")
public class ActivitiController {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private HistoryService historyService;

    @Autowired
    private UserMapper userMapper;

    @RequestMapping("/login")
    public ResultDto<User> login(String name) {
        logger.info("登录名：" + name);
        ResultDto<User> resultDto = new ResultDto<>();
        User user = userMapper.selectByName(name);
        if (user == null) return resultDto.fail("找不到用户");
        else return resultDto.success(user);
    }

    /**
     * 部署流程定义(流程图)
     * @param fileName 流程图名称
     * @return 部署信息
     */
    @RequestMapping("/deployBpmn")
    public ResultDto<Deployment> deployBpmn(String fileName) {
        Deployment deployment = repositoryService
                .createDeployment()
                .addClasspathResource("processes/" + fileName + ".bpmn")
                .deploy();
        return new ResultDto<Deployment>().success(deployment);
    }

    /**
     * 开启流程
     * @param processDefinitionKey 流程定义key
     * @param businessKey 业务键
     * @param variables 变量
     * @return 流程实例ID
     */
    @RequestMapping("/startProcess")
    public ResultDto<String> startProcess(String processDefinitionKey, String businessKey, String userId, Map<String, Object> variables) {
        Authentication.setAuthenticatedUserId(userId); // 设置提交人
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
        return new ResultDto<String>().success(processInstance.getProcessInstanceId());
    }

    /**
     * 根据用户查询待审批任务
     * @param processDefinitionKey 流程定义key
     * @param userId 用户ID
     * @return 任务列表
     */
    @RequestMapping("/queryTask")
    public ResultDto<List<TaskDto>> queryTask(String processDefinitionKey, int userId) {
        String roleIds = userMapper.selectById(userId).getRoleIds();
        List<Task> tasks = taskService.createTaskQuery()
                .processDefinitionKey(processDefinitionKey)
                .taskCandidateGroupIn(Arrays.asList(roleIds.split(",").clone()))
                .orderByTaskCreateTime()
                .desc()
                .list();
        return new ResultDto<List<TaskDto>>().success(toTaskDtos(tasks));
    }

    public List<TaskDto> toTaskDtos(List<Task> tasks) {
        return tasks.stream().map(it ->  {
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(it.getProcessInstanceId()).list().get(0);
            TaskDto dto = new TaskDto();
            dto.setId(it.getId());
            dto.setName(it.getName());
            dto.setCreateTime(it.getCreateTime());
            dto.setProcessInstanceId(it.getProcessInstanceId());
            if (StringUtils.isNotEmpty(processInstance.getStartUserId())) {
                dto.setUserName(userMapper.selectById(Integer.parseInt(processInstance.getStartUserId())).getName());
            }
            Map<String, Object> variables = taskService.getVariables(it.getId());
            if (!CollectionUtils.isEmpty(variables) && variables.get("day") != null) {
                dto.setDay(variables.get("day").toString());
            }
            return dto;
        }).collect(Collectors.toList());
    }

    /**
     * 执行审批任务
     * @param userId 提交人id
     * @param taskId 任务id
     * @param comment 意见
     * @param processInstanceId 流程实例id
     * @param approve 是否审批通过
     */
    @RequestMapping("/executeTask")
    public void executeTask(String userId, String taskId, String comment, String processInstanceId, boolean approve) {
        Map<String, Object> variables = new HashMap<>();
        variables.put("approve", approve);

        taskService.claim(taskId, userId); // 设置提交人
        taskService.setVariables(taskId, variables); // 设置变量
        taskService.addComment(taskId, processInstanceId, comment); // 设置审批意见
        taskService.complete(taskId); // 完成任务
    }

    @RequestMapping("/queryHistoryTask")
    public ResultDto<List<HistoryTaskDto>> queryHistoryTask(String processInstanceId) {
        List<HistoricTaskInstance> historicTaskInstances = historyService.createHistoricTaskInstanceQuery()
                .finished()
                .processInstanceId(processInstanceId)
                .orderByHistoricTaskInstanceEndTime().asc().list();
        // 查询历史审批人
//        List<String> userIds = historicTaskInstances.stream().map(TaskInfo::getAssignee).collect(Collectors.toList());
//        List<User> users = userIds.stream().map(it -> userMapper.selectById(Integer.parseInt(it))).collect(Collectors.toList());
        // 查询历史意见
        List<HistoryTaskDto> historyTaskDtos = historicTaskInstances.stream().map(it -> {
            HistoryTaskDto dto = new HistoryTaskDto();
            dto.setId(it.getId());
            if (StringUtils.isNotEmpty(it.getAssignee())) {
                dto.setUserName(userMapper.selectById(Integer.parseInt(it.getAssignee())).getName());
            }
            List<Comment> taskComments = taskService.getTaskComments(it.getId());
            if (!CollectionUtils.isEmpty(taskComments)) {
                dto.setComment(taskComments.get(0).getFullMessage());
            }
            dto.setStartTime(it.getStartTime());
            dto.setEndTime(it.getEndTime());
            return dto;
        }).collect(Collectors.toList());

        return new ResultDto<List<HistoryTaskDto>>().success(historyTaskDtos);
    }


    /**
     * 请假申请
     */
    @RequestMapping("/applyLeave")
    public void applyLeave(String userId, String reason, int day) {
        // 开启请假流程
        String processDefinitionKey = "leave";
        Map<String, Object> variables = new HashMap<>();
        variables.put("day", day);
        String processInstanceId = startProcess(processDefinitionKey, "", userId, variables).getData();
        // 完成请假申请任务
        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
        executeTask(userId, task.getId(), reason, processInstanceId, true);
    }
}
